package com.jic.market.impl.rest.discountamount;

import com.google.common.base.Joiner;
import com.jic.common.base.vo.AdminOperate;
import com.jic.market.common.exception.MarketErrorCodeEnum;
import com.jic.market.common.exception.MarketException;
import com.jic.market.entity.DiscountOrderDetail;
import com.jic.market.entity.DiscountProductDetail;
import com.jic.market.entity.DiscountPromotionDetail;
import com.jic.market.entity.overlay.OverlayGroupInfo;
import com.jic.market.entity.overlay.OverlayPromotionInfo;
import com.jic.market.enums.*;
import com.jic.market.impl.rest.discountamount.model.DiscountAmountModel;
import com.jic.market.impl.rest.discountamount.model.DiscountOrderModel;
import com.jic.market.impl.rest.discountamount.model.PromotionAmountModel;
import com.jic.market.impl.rest.discountamount.po.GoodsPo;
import com.jic.market.impl.rest.discountamount.po.OverlayPo;
import com.jic.market.impl.rest.discountamount.po.PromotionPo;
import com.jic.market.mapper.DiscountOrderDetailMapper;
import com.jic.market.mapper.DiscountProductDetailMapper;
import com.jic.market.mapper.DiscountPromotionDetailMapper;
import com.jic.market.mapper.PatchGrouponThemeEntityMapper;
import com.jic.market.mapper.overlay.OverlayGroupInfoMapper;
import com.jic.market.mapper.overlay.OverlayPromotionInfoMapper;
import com.jic.market.response.rest.discountamount.GiftDetail;
import com.jic.market.service.rest.discountamount.DiscountAmountModelService;
import com.jic.market.service.rest.discountamount.PromotionGoodsService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;

/**
 * @author yinhaijun
 * @date: 2020/4/10
 */
@Service
public class DiscountAmountModelServiceImpl implements DiscountAmountModelService {

    @Autowired
    private PromotionGoodsService promotionGoodsService;
    @Autowired
    private OverlayPromotionInfoMapper overlayPromotionInfoMapper;
    @Autowired
    private OverlayGroupInfoMapper overlayGroupInfoMapper;
    @Resource
    private DiscountProductDetailMapper discountProductDetailMapper;
    @Resource
    private DiscountPromotionDetailMapper discountPromotionDetailMapper;
    @Resource
    private DiscountOrderDetailMapper discountOrderDetailMapper;
    @Resource
    private PatchGrouponThemeEntityMapper patchGrouponThemeEntityMapper;
    @Override
    public List<DiscountAmountModel> build(Map<Long, GoodsPo> goodsPoMap, List<String> couponCodeList, Map<String, List<GiftDetail>> giftMap, String grouponPromotionCode, FrontPromotionTypeEnum frontPromotionTypeEnum) {
        Map<Long, List<PromotionPo>> skuPromotionMap = promotionGoodsService.buildPromotionPoMap(goodsPoMap, couponCodeList, grouponPromotionCode, frontPromotionTypeEnum);
        Map<String, BigDecimal> promotionJoinTotalAmountMap = buildPromotionJoinTotalAmountMap(skuPromotionMap, goodsPoMap);
        List<DiscountAmountModel> discountAmountModelList = buildBusinessModel(skuPromotionMap, promotionJoinTotalAmountMap, goodsPoMap, giftMap);
        return discountAmountModelList;
    }

    @Override
    public DiscountOrderModel build(String orderNo, List<String> thirdProductCodeList) {
        DiscountOrderDetail discountOrderDetailQ = new DiscountOrderDetail();
        discountOrderDetailQ.setOrderNo(orderNo);
        List<DiscountOrderDetail> discountOrderDetailList = discountOrderDetailMapper.query(discountOrderDetailQ);
        if(null == discountOrderDetailList || discountOrderDetailList.isEmpty()){
            throw new MarketException(MarketErrorCodeEnum.PARAM_ERROR, "没有对应的订单数据");
        }
        DiscountOrderModel discountOrderModel = new DiscountOrderModel();
        BeanUtils.copyProperties(discountOrderDetailList.get(0), discountOrderModel);
        discountOrderModel.setDiscountOrderStatus(DiscountOrderStatusEnum.getByCode(discountOrderDetailList.get(0).getDiscountOrderStatus()));
        List<DiscountAmountModel> discountAmountModelList = new ArrayList<>();
        if(null == thirdProductCodeList || thirdProductCodeList.isEmpty()){
            DiscountProductDetail discountProductDetailQ = new DiscountProductDetail();
            discountProductDetailQ.setOrderNo(orderNo);
            List<DiscountProductDetail> discountProductDetailList = discountProductDetailMapper.query(discountProductDetailQ);
            queryDiscountProductDetailList(orderNo, discountAmountModelList, discountProductDetailList);
        }
        else{
            thirdProductCodeList.forEach(thirdProductCode ->{
                DiscountProductDetail discountProductDetailQ = new DiscountProductDetail();
                discountProductDetailQ.setOrderNo(orderNo);
                discountProductDetailQ.setThirdSkuId(thirdProductCode);
                List<DiscountProductDetail> discountProductDetailList = discountProductDetailMapper.query(discountProductDetailQ);
                queryDiscountProductDetailList(orderNo, discountAmountModelList, discountProductDetailList);
            });
        }
        discountOrderModel.setDiscountAmountModelList(discountAmountModelList);
        return discountOrderModel;
    }

    @Override
    public void check(String orderNo, DiscountAmountServiceOperateEnum discountAmountServiceOperate) {
        DiscountOrderDetail discountOrderDetailQ = new DiscountOrderDetail();
        discountOrderDetailQ.setOrderNo(orderNo);
        List<DiscountOrderDetail> discountOrderDetailList = discountOrderDetailMapper.query(discountOrderDetailQ);
        if(discountAmountServiceOperate == DiscountAmountServiceOperateEnum.CREATE){
            if(null != discountOrderDetailList && !discountOrderDetailList.isEmpty()){
                throw new MarketException(MarketErrorCodeEnum.ORDER_IS_EXISTE, "订单已存在");
            }
        }else{
            DiscountOrderDetail discountOrderDetail = discountOrderDetailList.get(0);
            if(discountAmountServiceOperate == DiscountAmountServiceOperateEnum.PAY){
                if(!discountOrderDetail.getDiscountOrderStatus().equals(DiscountOrderStatusEnum.CREATE)){
                    throw new MarketException(MarketErrorCodeEnum.ORDER_IS_EXISTE, "订单不是创建状态");
                }
            }else if(discountAmountServiceOperate == DiscountAmountServiceOperateEnum.REFUND){
                if(!discountOrderDetail.getDiscountOrderStatus().equals(DiscountOrderStatusEnum.PAY) || !discountOrderDetail.getDiscountOrderStatus().equals(DiscountOrderStatusEnum.REFUND)) {
                    throw new MarketException(MarketErrorCodeEnum.ORDER_IS_EXISTE, "订单未支付");
                }
            }
        }
    }

    private void queryDiscountProductDetailList(String orderNo, List<DiscountAmountModel> discountAmountModelList, List<DiscountProductDetail> discountProductDetailList) {
        if(null == discountProductDetailList || discountProductDetailList.isEmpty()){
            throw new MarketException(MarketErrorCodeEnum.PARAM_ERROR, "查不到对应的明细记录");
        }
        if (null != discountProductDetailList && !discountProductDetailList.isEmpty()) {
            discountProductDetailList.forEach(discountProductDetail -> {
                DiscountAmountModel discountAmountModel = new DiscountAmountModel();
                BeanUtils.copyProperties(discountProductDetail, discountAmountModel);
                DiscountPromotionDetail discountPromotionDetailQ = new DiscountPromotionDetail();
                discountPromotionDetailQ.setOrderNo(orderNo);
                discountPromotionDetailQ.setSkuId(discountProductDetail.getSkuId());
                List<DiscountPromotionDetail> discountPromotionDetailList = discountPromotionDetailMapper.query(discountPromotionDetailQ);
                if (null != discountPromotionDetailList && !discountPromotionDetailList.isEmpty()) {
                    DiscountAmountModel.ExclusiveGroup exclusiveGroup = new DiscountAmountModel.ExclusiveGroup();
                    List<PromotionAmountModel> promotionAmountModelList = new ArrayList<>();
                    discountPromotionDetailList.forEach(discountPromotionDetail -> {
                        PromotionAmountModel promotionAmountModel = new PromotionAmountModel();
                        BeanUtils.copyProperties(discountPromotionDetail, promotionAmountModel);
                        if (!StringUtils.isEmpty(discountPromotionDetail.getCouponCodes())) {
                            promotionAmountModel.setCouponCodeList(Arrays.asList(discountPromotionDetail.getCouponCodes().split(",")));
                        }
                        promotionAmountModel.setFrontPromotionTypeEnum(FrontPromotionTypeEnum.getByCode(discountPromotionDetail.getFrontPromType()));
                        promotionAmountModel.setDiscountDetailStatus(DiscountDetailStatusEnum.getByCode(discountPromotionDetail.getDiscountDetailStatus()));
                        promotionAmountModelList.add(promotionAmountModel);
                    });
                    exclusiveGroup.setPromotionAmountModelList(promotionAmountModelList);
                    discountAmountModel.setExclusiveGroup(exclusiveGroup);
                }

                discountAmountModelList.add(discountAmountModel);
            });
        }
    }

    @Override
    public void save(DiscountOrderModel discountOrderModel, AdminOperate adminOperate) {
        DiscountOrderDetail discountOrderDetail = new DiscountOrderDetail();
        BeanUtils.copyProperties(discountOrderModel, discountOrderDetail);
        discountOrderDetail.setDiscountOrderStatus(discountOrderModel.getDiscountOrderStatus().getCode());
        discountOrderDetail.setDeleteFlag(false);
        if(null != discountOrderDetail.getId() && !discountOrderDetail.getId().equals(0L)){
            if(null != adminOperate) {
                discountOrderDetail.setUpdator(adminOperate.getOperator());
                discountOrderDetail.setUpdatorName(adminOperate.getOperateName());
            }
            discountOrderDetail.setUpdateTime(new Date());
            discountOrderDetailMapper.update(discountOrderDetail);
        }else {
            if(null != adminOperate){
                discountOrderDetail.setDeptId(adminOperate.getDeptId());
                discountOrderDetail.setDeptType(adminOperate.getDeptType().getCode());
                discountOrderDetail.setCreator(adminOperate.getOperator());
                discountOrderDetail.setCreatorName(adminOperate.getOperateName());
            }
            discountOrderDetail.setCreateTime(new Date());
            discountOrderDetailMapper.insert(discountOrderDetail);
        }

        List<DiscountAmountModel> discountAmountModels = discountOrderModel.getDiscountAmountModelList();
        if(null == discountAmountModels || discountAmountModels.isEmpty()){
            return;
        }
        for(DiscountAmountModel discountAmountModel : discountAmountModels){
            if(null == discountAmountModel.getDiscountTotalAmount() || BigDecimal.ZERO.compareTo(discountAmountModel.getDiscountTotalAmount()) == 0){
                continue;
            }
            DiscountProductDetail discountProductDetail = new DiscountProductDetail();
            BeanUtils.copyProperties(discountOrderModel, discountProductDetail);
            BeanUtils.copyProperties(discountAmountModel, discountProductDetail);
            discountProductDetail.setDeleteFlag(false);
            if(null != discountProductDetail.getId() && !discountOrderDetail.getId().equals(0L)){
                if(null != adminOperate) {
                    discountProductDetail.setUpdator(adminOperate.getOperator());
                    discountProductDetail.setUpdatorName(adminOperate.getOperateName());
                }
                discountProductDetail.setUpdateTime(new Date());
                discountProductDetailMapper.update(discountProductDetail);
            }else {
                if(null != adminOperate){
                    discountProductDetail.setDeptId(adminOperate.getDeptId());
                    discountProductDetail.setDeptType(adminOperate.getDeptType().getCode());
                    discountProductDetail.setCreator(adminOperate.getOperator());
                    discountProductDetail.setCreatorName(adminOperate.getOperateName());
                }
                discountProductDetail.setCreateTime(new Date());
                discountProductDetailMapper.insert(discountProductDetail);
            }
            DiscountAmountModel.ExclusiveGroup exclusiveGroup = discountAmountModel.getExclusiveGroup();
            if(null != exclusiveGroup){
                List<PromotionAmountModel> promotionAmountModelList = exclusiveGroup.getPromotionAmountModelList();
                if(null != promotionAmountModelList && !promotionAmountModelList.isEmpty()){
                    promotionAmountModelList.forEach(promotionAmountModel -> {
                        savePromotionAmountModel(discountOrderModel.getOrderNo(), discountAmountModel.getSkuId(), discountAmountModel.getThirdSkuId(), promotionAmountModel, adminOperate);
                    });
                }
            }
            DiscountAmountModel.OverlayGroup overlayGroup = discountAmountModel.getOverlayGroup();
            if(null != overlayGroup){
                List<PromotionAmountModel> promotionAmountModelList = overlayGroup.getPromotionAmountModelList();
                if(null != promotionAmountModelList && !promotionAmountModelList.isEmpty()){
                    promotionAmountModelList.forEach(promotionAmountModel -> {
                        savePromotionAmountModel(discountOrderModel.getOrderNo(), discountAmountModel.getSkuId(), discountAmountModel.getThirdSkuId(), promotionAmountModel, adminOperate);
                    });
                }
            }
        }
    }

    void savePromotionAmountModel(String orderNo, Long skuId, String thirdSkuId, PromotionAmountModel promotionAmountModel, AdminOperate adminOperate){
        DiscountPromotionDetail discountPromotionDetail = new DiscountPromotionDetail();
        discountPromotionDetail.setId(promotionAmountModel.getId());
        discountPromotionDetail.setDiscountDetailStatus(promotionAmountModel.getDiscountDetailStatus().getCode());
        discountPromotionDetail.setOrderNo(orderNo);
        discountPromotionDetail.setDiscountDetailStatus(promotionAmountModel.getDiscountDetailStatus().getCode());
        if(null != promotionAmountModel.getCouponCodeList() && !promotionAmountModel.getCouponCodeList().isEmpty()){
            discountPromotionDetail.setCouponCodes(Joiner.on(",").join(promotionAmountModel.getCouponCodeList()));
        }
        discountPromotionDetail.setPromotionId(promotionAmountModel.getPromotionId());
        discountPromotionDetail.setFrontPromType(promotionAmountModel.getFrontPromotionTypeEnum().getCode());
        discountPromotionDetail.setPromType(promotionAmountModel.getFrontPromotionTypeEnum().getPromType().getCode());
        discountPromotionDetail.setSkuId(skuId);
        discountPromotionDetail.setThirdSkuId(thirdSkuId);
        discountPromotionDetail.setPromotionDiscountSingleAmount(promotionAmountModel.getPromotionDiscountSingleAmount());
        discountPromotionDetail.setPromotionDiscountTotalAmount(promotionAmountModel.getPromotionDiscountTotalAmount());
        discountPromotionDetail.setDeleteFlag(false);
        if(null != promotionAmountModel.getId() && !promotionAmountModel.getId().equals(0L)){
            if(null != adminOperate) {
                discountPromotionDetail.setUpdator(adminOperate.getOperator());
                discountPromotionDetail.setUpdatorName(adminOperate.getOperateName());
            }
            discountPromotionDetail.setUpdateTime(new Date());
            discountPromotionDetailMapper.update(discountPromotionDetail);
        }else {
            if(null != adminOperate){
                discountPromotionDetail.setDeptId(adminOperate.getDeptId());
                discountPromotionDetail.setDeptType(adminOperate.getDeptType().getCode());
                discountPromotionDetail.setCreator(adminOperate.getOperator());
                discountPromotionDetail.setCreatorName(adminOperate.getOperateName());
            }
            discountPromotionDetail.setCreateTime(new Date());
            discountPromotionDetailMapper.insert(discountPromotionDetail);
        }
    }

    @Override
    public Integer countNum(String promotionId, Long skuId, String thirdUserId) {
        return discountProductDetailMapper.countNumByPromotionIdAndSkuIdAndThirdUserId(promotionId, skuId, thirdUserId);
    }

    @Override
    public Integer countNum(String promotionId, Long skuId) {
        return discountProductDetailMapper.countNumByPromotionIdAndSkuId(promotionId, skuId);
    }

    private Map<String, BigDecimal> buildPromotionJoinTotalAmountMap(Map<Long, List<PromotionPo>> skuPromotionMap, Map<Long, GoodsPo> goodsPoMap) {
        Map<String, BigDecimal> promotionJoinTotalAmountMap = new HashMap<>();
        skuPromotionMap.forEach((skuId, promotionPoList) ->{
            GoodsPo goodsPo = goodsPoMap.get(skuId);
            promotionPoList.forEach(promotionPo ->{
                BigDecimal joinTotalAmount = promotionJoinTotalAmountMap.get(promotionPo.getPromotionId());
                if(null == joinTotalAmount){
                    promotionJoinTotalAmountMap.put(promotionPo.getPromotionId(), goodsPo.getTotalAmount());
                }else {
                    promotionJoinTotalAmountMap.put(promotionPo.getPromotionId(), new BigDecimal(joinTotalAmount.add(goodsPo.getTotalAmount()).doubleValue()));
                }
            });
        });
        return promotionJoinTotalAmountMap;
    }
    private List<DiscountAmountModel> buildBusinessModel(Map<Long, List<PromotionPo>> skuPromotionMap, Map<String, BigDecimal> promotionJoinTotalAmountMap, Map<Long, GoodsPo> goodsPoMap, Map<String, List<GiftDetail>> giftMap) {
        List<DiscountAmountModel> discountAmountModelList = new ArrayList<>();

        skuPromotionMap.forEach((skuId, promotionPoList) ->{
            DiscountAmountModel discountAmountModel = DiscountAmountModel.init(skuId);
            discountAmountModel.setThirdSkuId(goodsPoMap.get(skuId).getThirdSkuId());
            discountAmountModel.setNum(goodsPoMap.get(skuId).getNum());
            OverlayPo overlayPo = queryOverlayPromotionIds(promotionPoList);
            if(null != overlayPo){
                discountAmountModel.getOverlayGroup().setOverlayId(overlayPo.getOverlayId());
                discountAmountModel.getOverlayGroup().setOverlayGroupId(overlayPo.getOverlayGroupId());
                discountAmountModel.getOverlayGroup().setFullAmountReduceFlag(overlayPo.getFullAmountReduceFlag());
            }
            promotionPoList.forEach( promotionPo ->{
                PromotionAmountModel promotionAmountModel = new PromotionAmountModel();
                promotionAmountModel.setPromotionId(promotionPo.getPromotionId());
                promotionAmountModel.setPromotionCode(promotionPo.getPromotionId());
                // 优惠劵
                promotionAmountModel.setCouponCodeList(promotionPo.getCouponCodeList());
                promotionAmountModel.setOverlayAppFlag(promotionPo.getOverlayAppFlag()==1);
                promotionAmountModel.setOverlayAppNum(promotionPo.getOverlayAppNum());
                promotionAmountModel.setFrontPromotionTypeEnum(FrontPromotionTypeEnum.getByCode(promotionPo.getFrontPromotionType()));
                // 赠品
                if(promotionAmountModel.getFrontPromotionTypeEnum().getPromType() == PromotionTypeEnum.GIFT && null != giftMap){
                    promotionAmountModel.setRuleData(giftMap.get(promotionAmountModel.getPromotionId()));
                }
                promotionAmountModel.setJoinTotalAmount(promotionJoinTotalAmountMap.get(promotionPo.getPromotionId()));
                if(null != overlayPo && null != overlayPo.getOverlayPromotionIds() && overlayPo.getOverlayPromotionIds().contains(promotionAmountModel.getPromotionId())){
                    discountAmountModel.getOverlayGroup().getPromotionAmountModelList().add(promotionAmountModel);
                }else {
                    discountAmountModel.getExclusiveGroup().getPromotionAmountModelList().add(promotionAmountModel);
                }

            });
            // 如果是非满额减，则需要对overlayPromotionAmountModelList排序
            if(null != discountAmountModel.getOverlayGroup()
                    && "0".equals(discountAmountModel.getOverlayGroup().getFullAmountReduceFlag())
                    && null != discountAmountModel.getOverlayGroup().getPromotionAmountModelList()
                    && !discountAmountModel.getOverlayGroup().getPromotionAmountModelList().isEmpty()
                    && discountAmountModel.getOverlayGroup().getPromotionAmountModelList().size() >= 2){
                discountAmountModel.getOverlayGroup().getPromotionAmountModelList().sort((o1, o2) -> {
                    Integer sort1 = querySortValue(o1.getFrontPromotionTypeEnum());
                    Integer sort2 = querySortValue(o2.getFrontPromotionTypeEnum());
                    int i = sort1 > sort2 ? 1 : -1;
                    return i;
                });
            };

            discountAmountModelList.add(discountAmountModel);
        });
        return discountAmountModelList;
    }

    // todo 需要查询排序规则
    private Integer querySortValue(FrontPromotionTypeEnum frontPromotionTypeEnum) {
        return 1;
    }
    private OverlayPo queryOverlayPromotionIds(List<PromotionPo> promotionPoList) {
        List<String> promotionIds = new ArrayList<>();
        if(null != promotionPoList && !promotionPoList.isEmpty()){
            promotionPoList.forEach(promotionPo -> {
                promotionIds.add(promotionPo.getPromotionId());
            });
        }else {
            return null;
        }
        String overlayGroupId = overlayPromotionInfoMapper.queryOverlayGroupIdByPromotionIds(promotionIds);
        if(null == overlayGroupId || overlayGroupId.equals("")){
            return null;
        }
        OverlayPromotionInfo overlayPromotionInfoQ = new OverlayPromotionInfo();
        overlayPromotionInfoQ.setOverlayGroupId(overlayGroupId);
        List<OverlayPromotionInfo> overlayPromotionInfoList = overlayPromotionInfoMapper.query(overlayPromotionInfoQ);
        if(null != overlayPromotionInfoList && !overlayPromotionInfoList.isEmpty()){
            OverlayPo overlayPo = new OverlayPo();
            overlayPo.setOverlayId(overlayPromotionInfoList.get(0).getOverlayId());
            overlayPo.setOverlayGroupId(overlayPromotionInfoList.get(0).getOverlayGroupId());
            List<String> overlayPromotionIds = new ArrayList<>();
            overlayPromotionInfoList.forEach(overlayPromotionInfo -> {
                overlayPromotionIds.add(overlayPromotionInfo.getPromotionId());
            });
            overlayPo.setOverlayPromotionIds(overlayPromotionIds);


            OverlayGroupInfo overlayGroupInfoQ = new OverlayGroupInfo();
            overlayGroupInfoQ.setOverlayGroupId(overlayPo.getOverlayGroupId());
            List<OverlayGroupInfo> overlayGroupInfoList = overlayGroupInfoMapper.query(overlayGroupInfoQ);
            if(null != overlayGroupInfoList && !overlayGroupInfoList.isEmpty() && !StringUtils.isEmpty(overlayGroupInfoList.get(0).getFullAmountReduceFlag())){
                overlayPo.setFullAmountReduceFlag(overlayGroupInfoList.get(0).getFullAmountReduceFlag());
            }else {
                overlayPo.setFullAmountReduceFlag("0");
            }
            return overlayPo;
        }
        return null;
    }

}
